home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / What's New? / Software Development Kits / Mac OS USB DDK / MacOS USB DDK 1.0b4 / NeptuneDDK / Examples / KeyboardModule / KBDHIDEmulation.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-26  |  7.4 KB  |  276 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        KBDHIDEmulation.c
  3.  
  4.     Contains:    Keyboard Emulation code
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <DriverServices.h>
  15. #include <USB.h>
  16.  
  17. #ifndef DDKBuild
  18. #include <USBPriv.h>
  19. #endif
  20.  
  21. #include "KeyboardModule.h"
  22.  
  23. extern    usbKeyboardPBStruct myKeyboardPB;
  24. extern    usbKeyboardPBStruct shimKeyboardPB;
  25.  
  26. void GetKeysPressed(USBHIDData * pKeysPressed);
  27.  
  28. OSStatus USBHIDInstallInterrupt(HIDInterruptProcPtr HIDInterruptFunction)
  29. {
  30.     myKeyboardPB.pSHIMInterruptRoutine = HIDInterruptFunction;
  31.     return 0;
  32. }
  33.  
  34. OSStatus USBHIDControlDevice(UInt32 theControlSelector, void * theControlData)
  35. {
  36.     switch (theControlSelector)
  37.     {
  38.         case kHIDSetLEDStateByBits:
  39.             shimKeyboardPB.hidReport[0] = *(UInt8*)theControlData;
  40.  
  41.             shimKeyboardPB.retryCount = kKeyboardRetryCount;
  42.             shimKeyboardPB.delayLevel = 0;                            
  43.             shimKeyboardPB.transDepth = 0;    
  44.             
  45.             shimKeyboardPB.pb.usbRefcon = kSetKeyboardLEDs;                    /* Start with setting the interface protocol */
  46.             KeyboardModuleInitiateTransaction(&shimKeyboardPB.pb);
  47.             break;
  48.             
  49.         case kHIDRemoveInterruptHandler:
  50.             myKeyboardPB.pSavedInterruptRoutine = nil;
  51.             myKeyboardPB.pSHIMInterruptRoutine = nil;
  52.             break;
  53.             
  54.         case kHIDEnableDemoMode:
  55.             USBExpertStatus(myKeyboardPB.deviceRef, "\pUSBHIDKeyboardModule: Demo Mode Enabled", myKeyboardPB.deviceRef);
  56.             myKeyboardPB.pSavedInterruptRoutine = myKeyboardPB.pSHIMInterruptRoutine;
  57.             myKeyboardPB.pSHIMInterruptRoutine = USBDemoKeyIn;
  58.             break;
  59.  
  60.         case kHIDDisableDemoMode:
  61.             USBExpertStatus(myKeyboardPB.deviceRef, "\pUSBHIDKeyboardModule: Demo Mode Disabled", myKeyboardPB.deviceRef);
  62.             myKeyboardPB.pSHIMInterruptRoutine = myKeyboardPB.pSavedInterruptRoutine;
  63.             break;
  64.  
  65.         default:
  66.             return paramErr;
  67.     }
  68.     return 0;
  69. }
  70.  
  71. void GetKeysPressed(USBHIDDataPtr pKeysPressed)
  72. {
  73. UInt8    i,keycount;
  74.     
  75.     keycount = 0;
  76.     for (i = 0; i < kKeyboardModifierBits; i++)
  77.     {
  78.         if (myKeyboardPB.oldHIDReport[0] & (1 << i))
  79.         {
  80.             pKeysPressed->kbd.usbkeycode[keycount++] = (0xe0 + i);
  81.         }
  82.     }
  83.             
  84.     if ((myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] == 0) || (myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] > 0x03))
  85.     {
  86.         for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++)
  87.         {
  88.             if (myKeyboardPB.oldHIDReport[i] > 0x03)
  89.             {
  90.                 pKeysPressed->kbd.usbkeycode[keycount++] = myKeyboardPB.oldHIDReport[i];
  91.             }
  92.         }                                                        
  93.     }
  94.     pKeysPressed->kbd.keycount = keycount;
  95. }
  96.  
  97.  
  98. OSStatus USBHIDGetDeviceInfo(UInt32 theInfoSelector, void * theInfo)
  99. {
  100. HIDInterruptProcPtr * pHIDIntProcPtr;
  101.  
  102.     switch (theInfoSelector)
  103.     {
  104.         case kHIDGetCurrentKeys:
  105.             GetKeysPressed((USBHIDDataPtr)theInfo);
  106.             break;
  107.  
  108.         case kHIDGetInterruptHandler:
  109.             pHIDIntProcPtr = (HIDInterruptProcPtr *)theInfo;  
  110.             *pHIDIntProcPtr = myKeyboardPB.pSHIMInterruptRoutine;
  111.             break;
  112.  
  113.         default:
  114.             return paramErr;
  115.     }
  116.     return 0;
  117. }
  118.  
  119. OSStatus USBHIDPollDevice(void)
  120. {
  121. #ifndef DDKBuild
  122.     USLPolledProcessDoneQueue();
  123. #endif
  124.     return kUSBNoErr;
  125. }
  126.  
  127. OSStatus USBHIDEnterPolledMode(void)
  128. {    
  129.     return unimpErr;
  130. }
  131.  
  132. OSStatus USBHIDExitPolledMode(void)
  133. {
  134.     return unimpErr;
  135. }
  136.  
  137. OSStatus USBHIDGetHIDDescriptor(USBHIDDescriptorPtr *hHIDDescriptor)
  138. {
  139. #pragma unused (hHIDDescriptor)
  140.     return unimpErr;
  141. }
  142.  
  143. void NotifyRegisteredHIDUser(UInt32 devicetype, UInt8 hidReport[])
  144. {
  145. #pragma unused (devicetype)
  146.  
  147. UInt8    i, j, newkey, oldkey, deltas;
  148.  
  149. UInt8        changedmodifiers, keycount;
  150. USBHIDData    theKeyboardData;
  151. Boolean        keypressedflag, keyreleasedflag;
  152.     
  153.     deltas = 0;
  154.     
  155.     if (myKeyboardPB.hidEmulationInit == false)
  156.     {
  157.         myKeyboardPB.hidEmulationInit = true;
  158.         for (i = 0; i < kKeyboardReportSize; i++)
  159.             myKeyboardPB.oldHIDReport[i] = 0;
  160.     };
  161.     
  162.     myKeyboardPB.oldHIDReport[1] = 0x0;
  163.     hidReport[1] = 0x0;
  164.     
  165.     for (i = 0; i < kKeyboardReportSize; i++)
  166.     {
  167.         if (hidReport[i] != myKeyboardPB.oldHIDReport[i])
  168.         {
  169.             deltas++;
  170.         }
  171.     }
  172.     
  173.     if ((myKeyboardPB.sendRawReportFlag) && deltas)
  174.     {
  175.         (*myKeyboardPB.pSHIMInterruptRoutine)(0xff, (void *)&hidReport[0]);
  176.     }
  177.     else
  178.     {
  179.         if (deltas)
  180.         {
  181.             keycount = 0;
  182.             changedmodifiers = hidReport[0] ^  myKeyboardPB.oldHIDReport[0];
  183.             
  184.             if (changedmodifiers)
  185.             {
  186.                 for (i = 0; i < kKeyboardModifierBits; i++)
  187.                 {
  188.                     if (changedmodifiers & (1 << i))
  189.                     {
  190.                         if (hidReport[0] & (1 << i))
  191.                         {
  192.                             theKeyboardData.kbd.usbkeycode[keycount++] = (0xe0 + i);
  193.                         }
  194.                         else
  195.                         {
  196.                             theKeyboardData.kbd.usbkeycode[keycount++] = (0x80e0 + i);
  197.                         }
  198.                     }
  199.                 }
  200.                 myKeyboardPB.oldHIDReport[0] = hidReport[0];
  201.             }
  202.             
  203.             if ((hidReport[kKeyboardOffsetToKeys] == 0) || (hidReport[kKeyboardOffsetToKeys] > 0x03))
  204.             {
  205.                 // While this double loop may look strange, I refer you to appendix C, of the HID Devices specification.
  206.                 // pp. 73 & 74 clearly state that report order is abitrary and does not reflect the order of events.
  207.                 // to quote: "The order of keycodes in array fields has no significance.  Order determination is done
  208.                 // by the host software comparing the contents of the previous report to the current report.  If two or 
  209.                 // more keys are pressed in one report, their order is indeterminate.  Keyboards may buffer events that
  210.                 // would have otherwise resulted in multiple events in a single report".
  211.                 
  212.                 // Because this specification (or lack thereof) states that the order is indeterminant, we have to 
  213.                 // check all the old keys against all the new keys...
  214.                 
  215.                 for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++)
  216.                 {
  217.                     keypressedflag = true;
  218.                     newkey = hidReport[i];
  219.                     
  220.                     keyreleasedflag = true;
  221.                     oldkey = myKeyboardPB.oldHIDReport[i];                            
  222.                     for (j = kKeyboardOffsetToKeys; j < (kKeyboardOffsetToKeys + kKeyboardReportKeys); j++)                                // then look through all the keys that were previously and are currently reported as pressed
  223.                     {                                    
  224.                         if (newkey == myKeyboardPB.oldHIDReport[j])        // was this new key already pressed?
  225.                         {                                
  226.                             keypressedflag = false;                        // if it was, then don't report it as being pressed.
  227.                         }
  228.                         
  229.                         if (oldkey == hidReport[j])                        // Is the old key still pressed?
  230.                         {                                
  231.                             keyreleasedflag = false;                    // If yes, then don't report it as being released
  232.                         }
  233.                     }
  234.                     if ((newkey > 0x03) && keypressedflag)
  235.                     {
  236.                         theKeyboardData.kbd.usbkeycode[keycount++] = newkey;
  237.                     }
  238.                     
  239.                     if ((oldkey > 0x03) && keyreleasedflag)
  240.                     {
  241.                         theKeyboardData.kbd.usbkeycode[keycount++] = (oldkey + 0x8000);
  242.                     }
  243.                     
  244.                     if (keycount > 20)                                    // a worse case scenario is:
  245.                     {                                                    // 4 modifier keys up
  246.                         break;                                            // the other 4 modifier keys down
  247.                     }                                                    // 6 previously reported keys up
  248.                 }                                                        // 6 newly reported keys down
  249.                                                                         // 6 + 6 + 4 + 4 = 20
  250.                 for (i = 0; i<kKeyboardReportSize; i++)
  251.                 {
  252.                     myKeyboardPB.oldHIDReport[i] = hidReport[i];
  253.                 };
  254.             }
  255.             
  256.             if ((myKeyboardPB.pSHIMInterruptRoutine) && keycount)
  257.             {
  258.                 theKeyboardData.kbd.keycount = keycount;
  259.                 (*myKeyboardPB.pSHIMInterruptRoutine)(kHIDKeyboardInterfaceProtocol, (void *)&theKeyboardData);
  260.             }
  261.         }
  262.     }
  263. }
  264.  
  265.  
  266. USBHIDModuleDispatchTable TheHIDModuleDispatchTable =
  267. {
  268.     (USBHIDInstallInterruptProcPtr)USBHIDInstallInterrupt,
  269.     (USBHIDPollDeviceProcPtr)USBHIDPollDevice,
  270.     (USBHIDControlDeviceProcPtr)USBHIDControlDevice,
  271.     (USBHIDGetDeviceInfoProcPtr)USBHIDGetDeviceInfo,
  272.     (USBHIDEnterPolledModeProcPtr)USBHIDEnterPolledMode,
  273.     (USBHIDExitPolledModeProcPtr)USBHIDExitPolledMode,
  274.     (USBHIDGetHIDDescriptorProcPtr)USBHIDGetHIDDescriptor
  275. };
  276.